package com.teamsun.service;

import com.alibaba.fastjson.JSONObject;
import com.teamsun.cache.CacheManager;
import com.teamsun.entity.HttpResult;
import com.teamsun.entity.IRequestInfo;
import com.teamsun.entity.OffLineDownLoad;
import com.teamsun.rptcfg.BaseRpt;
import com.teamsun.rptcfg.BaseRptColumn;
import com.teamsun.util.Constants;
import com.teamsun.util.RequestParamToMap;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>调用PCS离线下载服务</p>
 */
@Service("pcsOfflineDownload")
public class PCSOfflineDownload implements ICallThirdService {

    @Autowired
    private IShowRptService showRptService;

    @Autowired
    private HttpClientService httpClientService;

    @Autowired
    private CacheManager cacheManager;

    /**
     * 封装请求参数
     * @param request
     * @return
     */
    @Override
    public IRequestInfo wrapRequestInfo(HttpServletRequest request, String sysCode) {
        String rptId = request.getParameter("rptId");  // 报表ID
        String rptIdx = request.getParameter("rptIdx");  // 选中指标
        String rptDim = request.getParameter("rptDim");  // 选中维度
        String aliasRptName = request.getParameter("aliasRptName");  // 自定义文件名

        // 获取缓存的报表配置信息
        BaseRpt rptInfo = (BaseRpt) cacheManager.getRptCache(rptId);
        List<BaseRptColumn> conditionColumn = rptInfo.getConditionColumns();

        // 获取查询参数
        Map<String, String> paramMap = RequestParamToMap.convertToMap(request, conditionColumn);

        OffLineDownLoad offLineDownLoad =  showRptService.getQuerySQL(rptInfo, paramMap);
        String accessSysCode = rptInfo.getAccessSysCode();
        String offLineDownLoadURL = accessSysCode + "." + Constants.OFFLINEDOWNLOADURL;
        // 调用离线下载服务的地址
        String offLineURL = (String) cacheManager.getCacheValue(offLineDownLoadURL);
        // 报表配置文件所在机器SFTP访问端口号
        String ftpPort = (String) cacheManager.getCacheValue(Constants.OFFLINEDOWNLOADPORT);
        // 报表配置文件所在机器SFTP访问用户名
        String ftpUser = (String) cacheManager.getCacheValue(Constants.OFFLINEDOWNLOADUSER);
        // 报表配置文件所在机器SFTP访问密码
        String ftpPass = (String) cacheManager.getCacheValue(Constants.OFFLINEDOWNLOADPASS);
        // 报表配置文件所在机器IP地址
        String ftpIP = (String) cacheManager.getCacheValue(Constants.OFFLINEDOWNLOADIP);
        // 报表表头文件名
        String rptHeaderFileName = "RPT_" + rptId + ".xlsx";
        // 报表表头文件存放路径
        String rptHeaderFilePath = (String) cacheManager.getCacheValue(Constants.RPTHEADERPATH);
        String ftpFileUrl = rptHeaderFilePath + "/" + rptHeaderFileName;

        offLineDownLoad.setFtpPort(ftpPort);
        offLineDownLoad.setFtpUser(ftpUser);
        offLineDownLoad.setFtpPass(ftpPass);
        offLineDownLoad.setFtpIp(ftpIP);
        offLineDownLoad.setFtpFileUrl(ftpFileUrl);
        offLineDownLoad.setReptName(rptInfo.getRptName());
        String userId = request.getParameter("userId");
        offLineDownLoad.setUserId(userId);
        offLineDownLoad.setAliasRptName(aliasRptName);
        offLineDownLoad.setItemCode(sysCode);

        // 获取报表的查询条件
        List<Map<String, String>> paramList = new ArrayList<Map<String, String>>();
        if(paramMap != null && paramMap.size() > 0) {
            for(BaseRptColumn rptColumn : conditionColumn) {
                String isSQLColumn = rptColumn.getIsSQLColumn();
                if(Constants.YES.equals(isSQLColumn) || StringUtils.isBlank(isSQLColumn)) {
                    String aliasField = rptColumn.getAliasField();
                    String colName = rptColumn.getName();
                    String conditionType = rptColumn.getConditionType();  // 查询条件类型
                    String paramValue = paramMap.get(aliasField);  // 参数值

                    if (StringUtils.isNotBlank(paramValue) && !Constants.CONSTANTS_UNDEFINED.equalsIgnoreCase(paramValue)) {
                        Map<String, String> map = new HashMap<String, String>();
                        // 如果列是查询列且类型为下拉框，则需要转义(将编码转换为名称)
                        if(Constants.CONDITIONTYPE_SELECT.equals(conditionType)) {
                            Map<String, String> optionValue = rptColumn.getOptionValue();
                            paramValue = optionValue.get(paramValue);
                        }
                        if(Constants.CONDITIONTYPE_MULTI_SELECT.equals(conditionType)) {
                            Map<String, String> optionValue = rptColumn.getOptionValue();
                            String[] values = paramValue.split(",");
                            String transformValue = "";
                            for(String value : values) {
                                transformValue = transformValue + optionValue.get(value) + ",";
                            }
                            if(transformValue.endsWith(",")) {
                                transformValue = transformValue.substring(0, transformValue.length() - 1);
                            }
                            paramValue = transformValue;
                        }
                        map.put("name", colName);
                        map.put("value", paramValue);
                        paramList.add(map);
                    } else {
                        // 查询条件是日期区间
                        if(Constants.CONDITIONTYPE_DATE_RANGE.equals(conditionType)) {
                            String dateStart = paramMap.get(aliasField + "_start");
                            String dateEnd = paramMap.get(aliasField + "_end");
                            if(StringUtils.isNotBlank(dateStart) || StringUtils.isNotBlank(dateEnd)) {
                                if(StringUtils.isNotBlank(dateStart)) {
                                    Map<String,String> map = new HashMap<String, String>();
                                    map.put("name", "起始时间");
                                    map.put("value", dateStart);
                                    paramList.add(map);
                                }
                                if(StringUtils.isNotBlank(dateEnd)) {
                                    Map<String,String> map = new HashMap<String, String>();
                                    map.put("name", "结束时间");
                                    map.put("value", dateEnd);
                                    paramList.add(map);
                                }
                            }
                        } else if(Constants.CONDITIONTYPE_TREE.equals(conditionType)) {
                            String treeData = paramMap.get(aliasField + "Id");
                            if(StringUtils.isNotBlank(treeData)) {
                                treeData = treeData.replaceAll("\'", "");
                                treeData = treeData.replaceAll("\"", "");
                                Map<String, String> map = new HashMap<String, String>();
                                map.put("name", colName);
                                map.put("value", treeData);

                                paramList.add(map);
                            }
                        } else if(Constants.CONDITIONTYPE_VALUE_RANGE.equals(conditionType)) {
                            String dateStart = paramMap.get(aliasField + "_start");
                            String dateEnd = paramMap.get(aliasField + "_end");
                            if(StringUtils.isNotBlank(dateStart) || StringUtils.isNotBlank(dateEnd)) {
                                Map<String, String> map = new HashMap<String, String>();
                                map.put("name", colName);
                                String value = "";
                                if(StringUtils.isNotBlank(dateStart)) {
                                    value = "大于" + dateStart;
                                }
                                if(StringUtils.isNotBlank(dateEnd)) {
                                    if(StringUtils.isNotBlank(value)) {
                                        value = "且小于" + dateEnd;
                                    } else {
                                        value = "小于" + dateEnd;
                                    }
                                }
                                map.put("value", value);
                                paramList.add(map);
                            }
                        }
                    }
                }
            }

            // 当查询条件不是来源于页面form表单，查询条件由上一个页面下钻而来
            List<BaseRptColumn> rptColumns = rptInfo.getRptColumns();
            List<BaseRptColumn> hiddenColumns = rptInfo.getHiddenRptColumns();
            String initParam = rptInfo.getInitCondition();
            String[] initParams = initParam.split(",");
            for(int i=0; i<initParams.length; i++) {
                boolean flag = true;
                String aliasField = initParams[i];
                String paramValue = paramMap.get(aliasField);  // 参数值
                String colName = "";
                if(rptColumns != null && rptColumns.size() > 0) {
                    for(BaseRptColumn rptColumn : rptColumns) {
                        String columnField = rptColumn.getAliasField();
                        String isCondition = rptColumn.getIsCondition();
                        if(!Constants.YES.equals(isCondition)) {  // 查询条件列已经拼接，在此需要过滤，防止重复
                            if(aliasField.equals(columnField)) {
                                colName = rptColumn.getName();
                                flag = false;
                                break;
                            }
                        }
                    }
                }
                if(flag) {
                    if(hiddenColumns != null && hiddenColumns.size() > 0) {
                        for(BaseRptColumn rptColumn : hiddenColumns) {
                            String columnField = rptColumn.getAliasField();
                            String isCondition = rptColumn.getIsCondition();
                            if(!Constants.YES.equals(isCondition)) {
                                if(aliasField.equals(columnField)) {  // 查询条件列已经拼接，在此需要过滤，防止重复
                                    colName = rptColumn.getName();
                                    break;
                                }
                            }
                        }
                    }
                }

                if(StringUtils.isNotBlank(paramValue) && !Constants.CONSTANTS_UNDEFINED.equalsIgnoreCase(paramValue)) {
                    Map<String, String> map = new HashMap<String, String>();
                    map.put("name", colName);
                    paramValue = paramValue.replaceAll("\'", "");
                    paramValue = paramValue.replaceAll("\"", "");
                    map.put("value", paramValue);
                    paramList.add(map);
                }
            }
        }

        // 获取下拉框明细信息
        List<Map<String, Object>> selectList = new ArrayList<Map<String, Object>>();  // 下拉框信息
        for(BaseRptColumn rptColumn : conditionColumn) {
            String aliasField = rptColumn.getAliasField();
            String colName = rptColumn.getName();
            String conditionType = rptColumn.getConditionType();  // 查询条件类型
            if(Constants.CONDITIONTYPE_SELECT.equals(conditionType) || Constants.CONDITIONTYPE_MULTI_SELECT.equals(conditionType)) {
                Map<String, String> optionValue = rptColumn.getOptionValue();
                Map<String,Object> selectMap = new HashMap<String, Object>();
                List<Map<String, String>> selectDetail = new ArrayList<Map<String, String>>();
                for(Map.Entry<String, String> entry : optionValue.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    if(StringUtils.isNotBlank(key)) {
                        Map<String, String> detailMap = new HashMap<String, String>();
                        detailMap.put("value", key);
                        detailMap.put("name", value);
                        selectDetail.add(detailMap);
                    }
                }
                selectMap.put("fieldName", aliasField);
                selectMap.put("opitions", selectDetail);
                selectList.add(selectMap);
            }
        }

        offLineDownLoad.setConditions(paramList);
        offLineDownLoad.setSelected(selectList);

        // 获取报表查询列
        List<String> fields = new ArrayList<String>();  // 显示列的field
        List<String> fieldName = new ArrayList<String>();  // 显示列的列名
        List<String> percentCols = new ArrayList<String>();  // 百分比列
        List<String> percentColName = new ArrayList<String>();  // 百分比列
        List<String> titleFields = new ArrayList<String>();  // 全量列的field

        List<BaseRptColumn> rptColumns = rptInfo.getRptColumns();
        List<BaseRptColumn> hidColumns = rptInfo.getHiddenRptColumns();
        List<BaseRptColumn> delColumns = new ArrayList<BaseRptColumn>();  // 需删除的列
        List<BaseRptColumn> reqColumns = new ArrayList<BaseRptColumn>();  // 传递的列信息
        List<BaseRptColumn> allColumns = new ArrayList<BaseRptColumn>();  // 传递的列信息

        reqColumns.addAll(rptColumns);
        allColumns.addAll(rptColumns);
        for(BaseRptColumn rptColumn : hidColumns) {
            if(!Constants.NO.equals(rptColumn.getIsQueryColumn())) {
                reqColumns.add(rptColumn);
                allColumns.add(rptColumn);
            }
        }
        if(StringUtils.isNotBlank(rptDim)) {
            for(int i=0; i<reqColumns.size(); i++) {
                BaseRptColumn rptColumn = reqColumns.get(i);
                String colType = rptColumn.getColType();
                String aliasField = rptColumn.getAliasField();
                if(Constants.YES.equals(colType) && !rptDim.contains(aliasField)) {
                    delColumns.add(rptColumn);
                    //rptColumns.remove(i);
                }
            }
        }
        if(StringUtils.isNotBlank(rptIdx)) {
            for(int i=0; i<reqColumns.size(); i++) {
                BaseRptColumn rptColumn = reqColumns.get(i);
                String colType = rptColumn.getColType();
                String isSumCol = rptColumn.getIsSumCol();
                String isCountCol = rptColumn.getIsCount();
                String aliasField = rptColumn.getAliasField();
                String lowerField = rptColumn.getField().toLowerCase();
                boolean flag = lowerField.contains("sum(") || lowerField.contains("count(");
                if(Constants.NO.equals(colType)) {
                    if(!rptIdx.contains(aliasField) || (!Constants.YES.equals(isSumCol) && !Constants.YES.equals(isCountCol) && !flag)) {
                        delColumns.add(rptColumn);
                        //rptColumns.remove(i);
                    }
                }
            }
        }

        if(delColumns.size() > 0) {
            reqColumns.removeAll(delColumns);
            delColumns.clear();
        }

        // 根据表头字段排序
        List<String> titleList = rptInfo.getExcelHeader();  // 按顺序获取Excel表头名称
        List<String> usedTitle = new ArrayList<String>();
        for(int i=0; i<titleList.size(); i++) {
            for(int j=0; j<reqColumns.size(); j++) {
                BaseRptColumn rptColumn = reqColumns.get(j);
                String colName = rptColumn.getName();
                String aliasField = rptColumn.getAliasField();
                if(colName.equals(titleList.get(i)) && !usedTitle.contains(aliasField)) {
                    fields.add(aliasField);
                    fieldName.add(colName);
                    if(Constants.NUMBERFORMATER_PERCENT_100.equals(rptColumn.getNumberFormat())) {
                        percentCols.add(aliasField);
                        percentColName.add(colName);
                    }
                    usedTitle.add(aliasField);
                    break;
                }
            }
        }

        List<String> usedInfo = new ArrayList<String>();
        for(int i=0; i<titleList.size(); i++) {
            for(int j=0; j<allColumns.size(); j++) {
                BaseRptColumn rptColumn = allColumns.get(j);
                String colName = rptColumn.getName();
                String aliasField = rptColumn.getAliasField();
                if(colName.equals(titleList.get(i)) && !usedInfo.contains(aliasField)) {
                    titleFields.add(aliasField);
                    usedInfo.add(aliasField);
                    break;
                }
            }
        }
        offLineDownLoad.setFields(fields);
        offLineDownLoad.setExcelHd(fieldName);

        offLineDownLoad.setExcelHdAll(titleList);
        offLineDownLoad.setExcelHdAllFields(titleFields);

        offLineDownLoad.setPercentHD(percentColName);
        offLineDownLoad.setPercentHDFields(percentCols);
        return offLineDownLoad;
    }

    /**
     * 调用外部服务
     * @param url 外部服务地址
     * @param requestInfo 调用外部服务传递的参数
     * @return
     */
    @Override
    public HttpResult callThirdService(String url, IRequestInfo requestInfo) {
        HttpResult httpResult = new HttpResult();
        String json = JSONObject.toJSONString(requestInfo);
        try {
            httpResult = httpClientService.doPostJson(url, json);
            String body = httpResult.getBody();
            JSONObject jsonObject = JSONObject.parseObject(body);
            String status = jsonObject.getString("status");
            String msg = jsonObject.getString("msg");
            httpResult.setStateCode(Integer.valueOf(status));
            httpResult.setBody(msg);
            System.out.println("****调用PCS离线下载服务[" + url + "]成功");
        } catch (Exception e) {
            System.out.println("***调用PCS离线下载服务[" + url + "]失败");
            e.printStackTrace();
            httpResult.setStateCode(0);
            httpResult.setBody("离线下载失败");
        }
        return httpResult;
    }
}
